<template>
  <div class="ee-progress fc eet" :style="{
    '--ee-progress-color': color,
    '--ee-progress-size': view,
  }" :type="type">
    <div v-if="type == 2 || type == 3 || type == 4" class="strip">
      <div class="bar">
        <div class="bar2 eet" :style="{ width: percent + '%' }"></div>
      </div>
    </div>

    <svg v-else-if="type == 1" class="dashboard"
         :viewBox="view ? (`-${view / 2 - 3} -${view / 2 - 3} ${94 + view} ${94 + view}`) : '0 0 100 100'">
      <linearGradient v-if="gradient" :id="gradientID" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop v-for="value, key in gradient" :key="key" :offset="key" :stop-color="value" />
      </linearGradient>
      <path class="bar" d="
        M 50 50
        m 0 47
        a 47 47 0 1 1 0 -94
        a 47 47 0 1 1 0 94
        "></path>
      <path class="bar2" d="
        M 50 50
        m 0 47
        a 47 47 0 1 1 0 -94
        a 47 47 0 1 1 0 94
        " :style="{
          'stroke-dasharray': value * 221.482 + 'px, 295.31px',
          'stroke-width': percent ? undefined : 0,
        }">
      </path>
    </svg>

    <svg v-else class="circle"
         :viewBox="view ? (`-${view / 2 - 3} -${view / 2 - 3} ${94 + view} ${94 + view}`) : '0 0 100 100'">
      <linearGradient v-if="gradient" :id="gradientID" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop v-for="value, key in gradient" :key="key" :offset="key" :stop-color="value" />
      </linearGradient>
      <path class="bar" d="
        M 50 50
        m 0 -47
        a 47 47 0 1 1 0 94
        a 47 47 0 1 1 0 -94
        "></path>
      <path class="bar2" d="
        M 50 50
        m 0 -47
        a 47 47 0 1 1 0 94
        a 47 47 0 1 1 0 -94
        " :style="{
          'stroke-dasharray': value * 295.31 + 'px, 295.31px',
          'stroke-width': percent ? undefined : 0,
        }">
      </path>
    </svg>

    <div class="progress fc" :style="type == 4 ? {
      transform: `translate(${-percent}%)`,
      left: percent + '%',
    } : undefined">
      <slot :i="this">{{ percent }}%</slot>
    </div>
  </div>
</template>

<script type="text/javascript">
import { injectStore } from "ee-vuex";
import unique from '../__use/unique'

/* ✔ */
export default injectStore({
  name: "ee-progress",
  emits: {
    /** value达到1时触发
     * @param i - 组件当前实例
     */
    completed: (i) => true,
  },
  data() {
    return {
      gradient: undefined,
    }
  },
  props: {
    /** 进度百分比，0-1 */
    value: {
      type: [Number, String],
      default: 0,
      set(value) {
        if (value < 0)
          value = 0;
        else if (value > 1)
          value = 1;
        if (this.value < 1 && value == 1)
          this.$emit("completed", this);
        return value;
      }
    },
    /** 进度条颜色，普通颜色或条形渐变色也可以通过--ee-progress-color设定
     * @type {object.<string, string> | string}
     * 
     * @example
     * 1. 普通颜色
     * yellow | #ff00ff
     * 
     * 2. 圆形和条形通用的对象形式设置渐变色，0%-100%为从左到右渐变
     * {
     *   '0%': 'red',
     *   '100%': 'yellow',
     * }
     * 
     * 3. 条形渐变色可以简单设置为
     * linear-gradient(to right, red , yellow);
     */
    color(value) {
      // 对象定义渐变
      if (value && value instanceof Object) {
        if (this.isStrip) {
          // 条形
          let ret = "linear-gradient(to right"
          for (const key in value)
            ret += `, ${value[key]} ${key}`;
          ret += ")";
          return ret;
        } else {
          this.gradient = value;
          // 圆形
          return `url(#${this.gradientID})`;
        }
      }
    },
    /** 进度条样式类型
     * 0: 圆形(默认)
     * 1: 仪表盘
     * 横条形 2: 百分比在右侧 | 3. 百分比在内测中间 | 4. 百分比在内测跟随进度
     * @type {('0' | '1' | '2' | '3' | '4')}
     */
    type: [String, Number],
    /** 进度条的粗细 */
    size: [String, Number],
  },
  computed: {
    /** 0 - 100 */
    percent: {
      get() { return Math.round(this.value * 100); },
      set(value) { this.value = value / 100; }
    },
    /** 是否是条形进度条 */
    isStrip() {
      return this.type >= 2 && this.type <= 4;
    },
    /** SVG渐变色的ID */
    gradientID() {
      return unique();
    },
    /** 进度条的粗细 */
    view() {
      let size = this.size;
      if (!size)
        return;

      if (this.isStrip) {
        // 条形：带单位，转换成em
        return isNaN(Number(size)) ? size : size + 'px';
      } else {
        // 圆形：纯数字，单位像素，方便计算svg的viewBox
        const number = Number(size);
        // 例如4.8px会是NaN
        if (isNaN(number)) {
          // 允许单位是px
          if (size.toString().endsWith('px')) {
            size = parseFloat(size);
          } else {
            size = undefined;
          }
        } else {
          size = number;
        }
        return size;
      }
    }
  },
})
</script>

<style lang="scss">
.ee-progress {
  --ee-progress-bgcolor: var(--text9);
  --ee-progress-color: var(--primary0);
  --ee-progress-size: .4em;

  position: relative;
  width: 8em;

  .bar {
    background: var(--ee-progress-bgcolor);
  }

  .bar2 {
    background: var(--ee-progress-color);
  }

  .strip {
    display: flex;
    align-items: center;
    flex: 1;

    .bar {
      height: var(--ee-progress-size);
      flex: 1;
      border-radius: 10em;
      overflow: hidden;

      .bar2 {
        height: 100%;
      }
    }
  }

  svg {
    stroke-width: var(--ee-progress-size);
    fill: none;

    path {
      stroke-linecap: round;
    }

    .bar {
      stroke: var(--ee-progress-bgcolor);
    }

    .bar2 {
      transition: all var(--ee-transition-duration) ease 0s;
      stroke: var(--ee-progress-color);
    }
  }

  .circle {
    :last-child {
      stroke-dashoffset: 0;
    }
  }

  .dashboard {
    path {
      stroke-dashoffset: -36.9137px;
    }

    .bar {
      stroke-dasharray: 221.482px, 295.31px;
    }
  }

  &[type='2'] {
    display: flex;

    .hline {
      flex: 1;
    }

    .progress {
      position: relative;
      margin-left: .5em;
      width: 2em;
    }
  }

  &[type='3'] {
    .progress {
      align-items: flex-end;
    }
  }

  &[type='4'] {
    .progress {
      width: auto;
      transition: all var(--ee-transition-duration);
      padding: 0 0.25em;
      background: var(--ee-progress-color);
      height: fit-content;
      top: unset;
      border-radius: 10em;
      line-height: 1.25;
    }
  }

  .progress {
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
  }
}
</style>